<?php

    #-------------------------------------------------------------#
	# This file is part of the Tekuna MVC Microframework for PHP. #
	# (c) 2009 Niels Jäckel <niels.jaeckel@tekuna.org>            #
	# Please visit http://tekuna.org/ for more information.       #
	#                                                             #
	# This software is licensed under the MIT License. Please     #
	# view the LICENSE file for the full text of this license.    #
    #-------------------------------------------------------------#


	Tekuna :: load('org.tekuna.core.request.Request');


	class RequestTest extends AbstractTekunaTestCase {

		protected
			$arrOriginalGET = array(),
			$arrOriginalPOST = array(),
			$arrOriginalSERVER = array(),
			$objRequest = NULL,

			$sTestFileName = '';


		public function setUp() {

			parent :: setUp();

			// init GET array
			$_GET = array('foo' => '123',
                          'bar' => '456',
                          'isoString' => utf8_decode('äöü'),
                          'recursive' => array('integer' => '987', 'float' => '2,345'));

			// init POST array
			$_POST = array('test' => 'value',
			               'test2' => 'value2',
			               'bodyHeight' => '1,9',
			               'recursive' => array('integer' => '1234', 'float' => '987,654'));

			// init SERVER array
			$_SERVER = array('REMOTE_ADDR' => '127.0.0.1',
			                 'REMOTE_PORT' => 3456,
			                 'HTTP_USER_AGENT' => 'TestClient/1.0',
			                 'HTTP_ACCEPT' => '*',
			                 'SERVER_PROTOCOL' => 'HTTP/1.1',
			                 'REQUEST_METHOD' => 'GET',
			                 'PHP_AUTH_USER' => 'authUser',
			                 'PHP_AUTH_PW' => 'authPassword',
			                 'HTTPS' => 'on');

			// create test file
			$sTestFileName = tempnam(sys_get_temp_dir(), 'tst');
			file_put_contents($sTestFileName, "line1\r\nline2\rline3\nline4");

			// init files
			$_FILES = array('testFile' => array('name' => 'myTestFile.txt', 'tmp_name' => 'file0815.txt', 'size' => '12345', 'type' => 'text/plain', 'error' => 0),
			                'testFile2' => array('name' => 'myTestFile2.txt', 'tmp_name' => 'file0816.txt', 'size' => '12346', 'type' => 'text/plain', 'error' => 0),
			                'testFile3' => array('name' => 'myTestFile3.txt', 'tmp_name' => 'file0817.txt', 'size' => '12347', 'type' => 'text/plain', 'error' => 0),
			                'realTestFile' => array('name' => 'RealTestFile.txt', 'tmp_name' => $sTestFileName, 'size' => filesize($sTestFileName), 'type' => 'text/plain', 'error' => 0));


			// store class members
			$this -> arrOriginalGET = $_GET;
			$this -> arrOriginalPOST = $_POST;
			$this -> arrOriginalSERVER = $_SERVER;
			$this -> sTestFileName = $sTestFileName;

			// instantiate the object
			$this -> objRequest = new Request();
		}


		public function testFilters() {

			// get request instance
			$objRequest = $this -> objRequest;

			// test default filters
			$this -> assertIdentical($objRequest -> getDefaultFilter(), new NoSpecialCharsFilter());
			$this -> assertIdentical($objRequest -> getDefaultFileFilter(), new EmptyFileFilter());

			// change filters
			$objRequest -> setDefaultFilter(new AlphanumericCharsFilter());
			$objRequest -> setDefaultFileFilter(new FileDataFilter(new UnixLineDelimitersFilter()));

			// test default filters again
			$this -> assertIdentical($objRequest -> getDefaultFilter(), new AlphanumericCharsFilter());
			$this -> assertIdentical($objRequest -> getDefaultFileFilter(), new FileDataFilter(new UnixLineDelimitersFilter()));

			// change back the filters
			$objRequest -> setDefaultFilter(new NoSpecialCharsFilter());
			$objRequest -> setDefaultFileFilter(new EmptyFileFilter());

			// test filter appliance for data filters in GET scope
			$this -> assertIdentical($objRequest -> getGETFilter('foo'), NULL);
			$this -> assertIdentical($objRequest -> getGETValue('foo'), '123');
			$objRequest -> setGETFilter('foo', new IntegerFilter());
			$this -> assertIdentical($objRequest -> getGETValue('foo'), 123);

			// test filter appliance for data filters in POST scope
			$this -> assertIdentical($objRequest -> getPOSTFilter('bodyHeight'), NULL);
			$this -> assertIdentical($objRequest -> getPOSTValue('bodyHeight'), '1,9');
			$objRequest -> setPOSTFilter('bodyHeight', new FloatFilter());
			$this -> assertIdentical($objRequest -> getPOSTValue('bodyHeight'), 1.9);

			// test recursive filters in GET
			$arrRecursiveData = $objRequest -> getGETValue('recursive');
			$this -> assertIdentical($arrRecursiveData['integer'], '987');
			$this -> assertIdentical($arrRecursiveData['float'], '2,345');

			// recursive conversion to integer
			$objRequest -> setGETFilter('recursive', new IntegerFilter());
			$arrRecursiveData = $objRequest -> getGETValue('recursive');
			$this -> assertIdentical($arrRecursiveData['integer'], 987);
			$this -> assertIdentical($arrRecursiveData['float'], 2);

			// recursive conversion to float
			$objRequest -> setGETFilter('recursive', new FloatFilter());
			$arrRecursiveData = $objRequest -> getGETValue('recursive');
			$this -> assertIdentical($arrRecursiveData['integer'], 987.0);
			$this -> assertIdentical($arrRecursiveData['float'], 2.345);


			// test recursive filters in POST
			$arrRecursiveData = $objRequest -> getPOSTValue('recursive');
			$this -> assertIdentical($arrRecursiveData['integer'], '1234');
			$this -> assertIdentical($arrRecursiveData['float'], '987,654');

			// recursive conversion to integer
			$objRequest -> setPOSTFilter('recursive', new IntegerFilter());
			$arrRecursiveData = $objRequest -> getPOSTValue('recursive');
			$this -> assertIdentical($arrRecursiveData['integer'], 1234);
			$this -> assertIdentical($arrRecursiveData['float'], 987);

			// recursive conversion to float
			$objRequest -> setPOSTFilter('recursive', new FloatFilter());
			$arrRecursiveData = $objRequest -> getPOSTValue('recursive');
			$this -> assertIdentical($arrRecursiveData['integer'], 1234.0);
			$this -> assertIdentical($arrRecursiveData['float'], 987.654);

			// test file filters
			$objTestFile = $objRequest -> getFile('realTestFile');
			$this -> assertIdentical(file_get_contents($objTestFile -> getTempName()), "line1\r\nline2\rline3\nline4");
			$this -> assertIdentical($objRequest -> getFileFilter('realTestFile'), NULL);

			// change file filter and compare again
			$objRequest -> setFileFilter('realTestFile', new FileDataFilter(new UnixLineDelimitersFilter()));
			$objTestFile = $objRequest -> getFile('realTestFile');
			$this -> assertIdentical(file_get_contents($objTestFile -> getTempName()), "line1\nline2\nline3\nline4");
			$this -> assertIdentical($objRequest -> getFileFilter('realTestFile'), new FileDataFilter(new UnixLineDelimitersFilter()));

			// set back the filters
			$objRequest -> setGETFilter('foo', new NoSpecialCharsFilter());
			$objRequest -> setGETFilter('bodyHeight', new NoSpecialCharsFilter());
			$objRequest -> setGETFilter('recursive', new NoSpecialCharsFilter());
			$objRequest -> setPOSTFilter('recursive', new NoSpecialCharsFilter());
			$objRequest -> setFileFilter('realTestFile', new EmptyFileFilter());
		}


		public function testRequestImport() {

			// get request instance
			$objRequest = $this -> objRequest;

			// check singleton instance type
			$this -> assertEqual(get_class($objRequest), 'Request');

			// check request protocol
			$this -> assertIdentical($objRequest -> getRequestProtocol(), 'HTTP/1.1');

			// check request method
			$this -> assertIdentical($objRequest -> getRequestMethod(), 'GET');
			$this -> assertTrue($objRequest -> isGETRequest());
			$this -> assertFalse($objRequest -> isPOSTRequest());

			// get authentication information
			$this -> assertTrue($objRequest -> hasAuthenticatedUser());
			$this -> assertIdentical($objRequest -> getAuthenticatedUser(), 'authUser');
			$this -> assertIdentical($objRequest -> getAuthenticatedPassword(), 'authPassword');

			// check value requests
			$this -> assertIdentical($objRequest -> getGETValue('foo'), '123');
			$this -> assertidentical(array_keys($objRequest -> getAllGETValues()), array_keys($this -> arrOriginalGET));
			$this -> assertIdentical($objRequest -> getPOSTValue('test'), 'value');
			$this -> assertidentical(array_keys($objRequest -> getAllPOSTValues()), array_keys($this -> arrOriginalPOST));

			$this -> assertTrue($objRequest -> isGETValueAvailable('foo'));
			$this -> assertFalse($objRequest -> isGETValueAvailable('nonExistentValue'));
			$this -> assertTrue($objRequest -> isPOSTValueAvailable('test'));
			$this -> assertFalse($objRequest -> isPOSTValueAvailable('nonExistentValue2'));

			// check exception on request of a non-existent value
			try {

				$objRequest -> getGETValue('nonExistentValue');
				$this -> fail();
			}
			catch (RequestException $e) {

				$this -> pass();
			}

			// check exception on request of a non-existent value
			try {

				$objRequest -> getPOSTValue('nonExistentValue2');
				$this -> fail();
			}
			catch (RequestException $e) {

				$this -> pass();
			}


			// test encodings
			$objRequest -> setDefaultFilter(new EmptyFilter());
			$objRequest -> setImportEncoding('UTF-8');
			$this -> assertIdentical($objRequest -> getGETValue('isoString'), utf8_decode('äöü'));
			$objRequest -> setImportEncoding('ISO-8859-15');
			$this -> assertIdentical($objRequest -> getGETValue('isoString'), 'äöü');

			// test HTTPS indication
			$this -> assertTrue($objRequest -> isHTTPSRequest());
		}


		public function testFiles() {

			// get request instance
			$objRequest = $this -> objRequest;

			// test file get functions
			$this -> assertTrue($objRequest -> isFileAvailable('testFile'));
			$this -> assertFalse($objRequest -> isFileAvailable('notExistingFile'));
			$this -> assertIdentical(count($objRequest -> getAllFiles()), 4);

			// request non-existing file
			try {

				$objRequest -> getFile('notExistingFile');
				$this -> fail();
			}
			catch (RequestException $e) {

				$this -> pass();
			}

			// test PostFile object
			$objPostFile = $objRequest -> getFile('testFile');
			$this -> assertIdentical($objPostFile -> getID(), 'testFile');
			$this -> assertIdentical($objPostFile -> getFileName(), 'myTestFile.txt');
			$this -> assertIdentical($objPostFile -> getTempName(), 'file0815.txt');
			$this -> assertIdentical($objPostFile -> getFileSize(), 12345);
			$this -> assertIdentical($objPostFile -> getMimeType(), 'text/plain');
			$this -> assertIdentical($objPostFile -> getErrorCode(), 0);
		}


		public function tearDown() {

			parent :: tearDown();

			// delete the test file
			@unlink($this -> sTestFileName);
		}
	}



